#!/bin/bash

# --- 配置部分 ---
# 定义所有进程的数组，每个元素是一个目录和可执行文件名的组合
# 格式: "目录名:可执行文件名"
declare -a PROCESSES=(
    "mosquitto-1.6.3:mosquitto"
    "data_report:client"
    "dev_udpclient:dev_udpclient"
    "http_show:http_show"
    "Metaverse:metaverse"
    "modbus:modbus"
    "stm32:stm32"
)

# 定义要使用的终端模拟器命令
# 根据你的桌面环境选择并取消注释相应的行。
# 默认使用 gnome-terminal。
#
# GNOME Terminal (GNOME 桌面环境):
# TERMINAL_CMD="gnome-terminal"
# Xterm (通用，通常预装):
# TERMINAL_CMD="xterm"
# Konsole (KDE 桌面环境):
# TERMINAL_CMD="konsole"
# Terminator (流行的平铺终端):
# TERMINAL_CMD="terminator"

TERMINAL_CMD="gnome-terminal" # 默认使用 gnome-terminal

# --- 函数定义 ---

# 检查上一个命令是否成功
check_status() {
    if [ $? -ne 0 ]; then
        echo "错误：$1 失败！"
        exit 1
    fi
}

# 编译所有进程
compile_all() {
    echo "--- 开始编译所有进程 ---"
    for process_info in "${PROCESSES[@]}"; do
        # 使用IFS分隔符读取数组元素，获取目录和可执行文件名
        IFS=':' read -r PROCESS_DIR PROCESS_EXEC <<< "$process_info"
        
        # 排除 mosquitto，因为它通常不需要编译
        if [ "$PROCESS_DIR" == "mosquitto-1.6.3" ]; then
            echo "跳过编译 $PROCESS_DIR (假定为预编译或已安装的程序)..."
            continue
        fi

        echo "进入目录: $PROCESS_DIR"
        cd "$PROCESS_DIR" || check_status "切换到 $PROCESS_DIR"
        echo "正在编译 $PROCESS_DIR..."
        
        # 先清理，忽略输出，确保干净编译
        make clean > /dev/null 2>&1 
        make || check_status "编译 $PROCESS_DIR"
        echo "编译 $PROCESS_DIR 完成。"
        
        cd .. || check_status "返回上一级目录"
    done
    echo "--- 所有进程编译完成 ---"
}

# 启动所有进程
start_all() {
    echo "--- 开始启动所有进程 ---"
    echo "每个进程将在新的终端窗口中启动。"
    echo "请确保你安装了 '$TERMINAL_CMD' 或修改脚本以使用你系统上的终端模拟器。"

    # 遍历所有进程并逐一启动
    for process_info in "${PROCESSES[@]}"; do
        IFS=':' read -r PROCESS_DIR PROCESS_EXEC <<< "$process_info"
        
        local COMMAND_TO_EXECUTE # 声明局部变量
        # 根据进程名称确定完整的执行路径和参数
        if [ "$PROCESS_EXEC" == "mosquitto" ]; then
            # 对于 mosquitto，直接使用命令名，假定它在系统的PATH中
            COMMAND_TO_EXECUTE="mosquitto"
        elif [ "$PROCESS_EXEC" == "http_show" ]; then
            # 对于 http_show，使用 sudo 启动
            COMMAND_TO_EXECUTE="sudo ./$PROCESS_DIR/$PROCESS_EXEC"
            echo "注意: 启动 http_show 可能需要您在新终端中输入密码。"
        elif [ "$PROCESS_EXEC" == "stm32" ]; then
            # 对于 stm32，带参数 8866 启动
            COMMAND_TO_EXECUTE="./$PROCESS_DIR/$PROCESS_EXEC 8866"
        else
            # 对于其他进程，使用相对路径
            COMMAND_TO_EXECUTE="./$PROCESS_DIR/$PROCESS_EXEC"
        fi

        TITLE="进程: $PROCESS_EXEC ($PROCESS_DIR)" # 为新终端窗口设置标题

        echo "启动 $PROCESS_EXEC (在新的终端中)..."
        
        # 根据选择的终端模拟器执行不同的命令
        # 'bash -c "COMMAND; echo ...; read -p ''; exit"' 结构用于:
        # 1. 执行目标进程 COMMAND
        # 2. 如果进程退出，打印提示信息
        # 3. 等待用户按 Enter 键 (read -p '')
        # 4. 关闭终端 (exit)
        if [ "$TERMINAL_CMD" == "gnome-terminal" ]; then
            "$TERMINAL_CMD" --title="$TITLE" -- bash -c "$COMMAND_TO_EXECUTE; echo '进程 $PROCESS_EXEC 已退出。按Enter键关闭此终端...'; read -p ''; exit" &
        elif [ "$TERMINAL_CMD" == "xterm" ]; then
            "$TERMINAL_CMD" -title "$TITLE" -e bash -c "$COMMAND_TO_EXECUTE; echo '进程 $PROCESS_EXEC 已退出。按Enter键关闭此终端...'; read -p ''; exit" &
        elif [ "$TERMINAL_CMD" == "konsole" ]; then
            konsole --new-tab -p tabtitle="$TITLE" -e bash -c "$COMMAND_TO_EXECUTE; echo '进程 $PROCESS_EXEC 已退出。按Enter键关闭此终端...'; read -p ''; exit" &
        elif [ "$TERMINAL_CMD" == "terminator" ]; then
            terminator -T "$TITLE" -e bash -c "$COMMAND_TO_EXECUTE; echo '进程 $PROCESS_EXEC 已退出。按Enter键关闭此终端...'; read -p ''; exit" &
        else
            echo "错误: 未知的终端模拟器 '$TERMINAL_CMD'。请手动启动或修改脚本。"
            exit 1
        fi
        
        # 这里的 $! 获取的是终端模拟器进程的PID，而不是实际运行的C程序的PID。
        # 对于停止操作，我们仍然依赖 killall 通过可执行文件名来杀死内部进程。
        echo "$PROCESS_EXEC 的终端启动PID: $!"
        
        # 如果是 mosquitto，等待更长时间确保启动
        if [ "$PROCESS_EXEC" == "mosquitto" ]; then
            echo "等待 Mosquitto 启动..."
            sleep 3 # 给 mosquitto 更多时间启动，确保其他进程可以连接
        else
            sleep 0.5 # 稍微等待一下，避免终端启动过快导致问题，或进程间有微小依赖
        fi
    done
    
    echo "--- 所有进程已启动 ---"
    echo "每个进程都在单独的终端窗口中运行。"
    echo "要停止所有进程，请运行 '$0 stop' 命令。"
    echo "注意: 关闭终端窗口也会停止相应的进程。"
}

# 停止所有进程
stop_all() {
    echo "--- 停止所有进程 ---"
    # 遍历所有可执行文件名称，并尝试杀死它们
    for process_info in "${PROCESSES[@]}"; do
        IFS=':' read -r PROCESS_DIR PROCESS_EXEC <<< "$process_info"
        echo "尝试停止: $PROCESS_EXEC"
        # killall 会根据进程名称杀死所有匹配的进程
        killall "$PROCESS_EXEC" > /dev/null 2>&1
    done
    echo "已尝试停止所有相关进程。"
    # 额外提示用户可能需要手动关闭终端
    echo "如果某些终端窗口没有自动关闭，请手动关闭它们。"
}

# 清理所有编译生成的文件
clean_all() {
    echo "--- 开始清理所有进程的编译文件 ---"
    for process_info in "${PROCESSES[@]}"; do
        IFS=':' read -r PROCESS_DIR PROCESS_EXEC <<< "$process_info"
        
        # 排除 mosquitto，因为它通常不需要清理编译文件
        if [ "$PROCESS_DIR" == "mosquitto-1.6.3" ]; then
            echo "跳过清理 $PROCESS_DIR (假定为预编译或已安装的程序)..."
            continue
        fi

        echo "进入目录: $PROCESS_DIR"
        cd "$PROCESS_DIR" || check_status "切换到 $PROCESS_DIR"
        echo "正在清理 $PROCESS_DIR..."
        make clean || check_status "清理 $PROCESS_DIR"
        echo "清理 $PROCESS_DIR 完成。"
        cd .. || check_status "返回上一级目录"
    done
    echo "--- 所有编译文件清理完成 ---"
}

# --- 脚本主逻辑 ---

case "$1" in
    compile)
        compile_all
        ;;
    start)
        start_all
        ;;
    restart)
        stop_all
        compile_all
        start_all
        ;;
    stop)
        stop_all
        ;;
    clean)
        clean_all
        ;;
    all)
        compile_all
        start_all
        ;;
    *)
        echo "用法: $0 {compile|start|restart|stop|clean|all}"
        echo "  compile : 编译所有进程。"
        echo "  start   : 启动所有进程，每个进程在新的终端窗口中显示。"
        echo "  restart : 停止、编译并启动所有进程。"
        echo "  stop    : 停止所有运行的进程。"
        echo "  clean   : 清理所有编译生成的文件。"
        echo "  all     : 编译并启动所有进程。"
        exit 1
        ;;
esac

echo "操作完成。"
